<template>
	<view class="chose-city">
		<!-- 城市搜索 -->
		<xl-search v-model="inputValue" :placeholder="placeholder" :margin="[0, 30, 20]" @change="searchChange"></xl-search>
		<!-- 城市列表 -->
		<scroll-view class="scroll-view" 
			scroll-y 
			scroll-with-animation="true" 
			enable-back-to-top="true" 
			:scroll-into-view="toIndex"
			@scroll="scrollHandle" 
			:style="scrollHeight"
		>
			<view class="block" v-if="!inputValue">
				<!-- 您所在的地区 -->
				<view class="area list-item" id="area">
					<view class="title-wrapp"><view class="c-title">您所在的地区</view></view>
					<view class="ul">
						<view class="li now" @click="locationCity(curCity)">
							<xl-icon v-if="curCity" name="xl-dizhi" color="#888" size="18" top="-1" right="5"></xl-icon>
							<xl-icon v-else name="xl-dingwei" color="#888" size="18" right="5"></xl-icon>
							<text class="city">{{ curCity ? curCity:'定位失败' }}</text>
						</view>
					</view>
				</view>
				<!-- 历史记录 -->
				<view class="area list-item" id="record" v-if="recordList.length">
					<view class="title-wrapp">
						<view class="c-title">
							<text class="l">历史记录</text>
						</view>
					</view>
					<view class="ul">
						<view class="li font-clamp" v-for="item in recordList" :key="item[valueName]" @click="selectCity(item)">
							{{ item[labelName] }}
						</view>
					</view>
				</view>
			</view>
			<!-- 城市列表  -->
			<view class="city-list" v-if="!inputValue">
				<view class="list list-item" v-for="(item, key) of cityList" :key="key" :id="item.nameType">
					<view class="c-title">{{ item.nameType }}</view>
					<view class="item" v-for="innerItem in item.list" :key="innerItem[valueName]" @click="selectCity(innerItem)">
						{{ innerItem[labelName] }}
					</view>
				</view>
			</view>
			<!-- 搜索列表  -->
			<view class="reach-content" v-show="inputValue">
				<view v-show="searchData.length">
					<view class="li" v-for="item in searchData" :key="item[valueName]" @click="selectCity(item)">
						{{item[labelName]}}
					</view>
				</view>
				<view class="has-no-data" v-show="hasNoData">没有找到匹配数据~</view>
			</view>
		</scroll-view>

		<!-- 字母列表 -->
		<view class="alphabet" @touchstart="touchStart" @touchend="touchEnd" @touchmove.stop="touchMove">
			<view v-for="(item, index) in alphabet" :key="index" @touchstart="getLetter" @touchend="setLetter" :id="item">
				<view class="item" :style="{color: currentLetter == item ? currentColor:color}">
					{{ item == 'area' ? '当前' : item == 'record' ? '历史' : item }}
				</view>
			</view>
		</view>
	</view>
</template>

<script setup>
	import { ref, computed, getCurrentInstance } from 'vue'
	import propsData from './props.js'
	const props = defineProps(propsData)

	// 组件方法
	const emits = defineEmits(['selectCity'])
	// 提供给父组件进行ref来切换
	defineExpose({ load })

	// 计算组件高度
	const scrollHeight = computed(()=>{
		let height = uni.getWindowInfo().screenHeight - uni.getWindowInfo().statusBarHeight - uni.$xl.upx2px(0 + props.reduceHeight)
		return `height: ${height}px;-webkit-overflow-scrolling:touch;`
	})
	
	// 字母表
	const alphabet = ref([
		"area",
		"record",
		"A",
		"B",
		"C",
		"D",
		"E",
		"F",
		"G",
		"H",
		"J",
		"K",
		"L",
		"M",
		"N",
		"P",
		"Q",
		"R",
		"S",
		"T",
		"W",
		"X",
		"Y",
		"Z"
	])
	
	// 城市列表  [首字母 -> list]
	const cityList = ref([])
	
	function load(list){
		const grouped = list.reduce((acc, item) => {
			const key = item[props.spellName].charAt(0); // 获取 spell 的首字母
			if (!acc[key]) acc[key] = []; // 初始化分组数组
			acc[key].push(item); // 将对象加入对应分组
			return acc;
		}, {});
		cityList.value = Object.keys(grouped).map(key => ({
			nameType: key,
			list: grouped[key]
		}));
	}
	
	//最近访问
	const recordList = ref([]) 
	//获取存储的最近访问
	uni.getStorage({
		key: 'visit_city',
		success: function(res) {
			recordList.value = res.data
		}
	});
	
	// 设置最近访问
	function setRecordList(item){
		//unshift 把数据插入到首位，与push相反
		recordList.value.unshift(item)
		//数组去重
		// array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
		// (function(必选初始值或计算结束返回值, 必选当前元素, 可选索引, 可选原数组),可选函数初始值)
		var obj = {};
		recordList.value = recordList.value.reduce(function(result, cur) {
			   obj[cur[props.labelName]] ? '' : obj[cur[props.labelName]] = true && result.push(cur);
			   return result;
			}, []);
		uni.setStorage({
			key: 'visit_city',
			data: recordList.value
		});
	}
	
	let curCity = ref('')
	function getLocation() {
		uni.getLocation({
			type: 'gcj02',
			geocode: true,
			success(res) {
				// #ifdef MP-WEIXIN
				console.log(res);
				uni.$xl.apis.getLocationCity(res.latitude, res.longitude, props.weiXinWebKey).then(res => {
					let c = res.city;
					curCity.value = c.substr(0, c.length - 1); 
				})
				// #endif
				// #ifndef MP-WEIXIN
				let c = res.address.city;
				curCity.value = c.substr(0, c.length - 1); 
				// #endif
			},
			fail(err) {
				console.log('地理位置获取失败');
				console.log(err);
				if(err.errMsg == 'getLocation:fail getLocation:fail 获取定位权限失败'){
					uni.$xl.showModal({
					  title: '提示',
					  content: '我们需要申请手机的定位权限，为您提供方便的位置信息服务',
					  success({confirm, cancel}) {
						 if(confirm) {
							 let system = uni.getSystemInfoSync();// 获取系统信息
							 if (system.platform == 'android') {
								var Intent = plus.android.importClass('android.content.Intent');
								var Settings = plus.android.importClass('android.provider.Settings');
								var intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
								var main = plus.android.runtimeMainActivity();
								main.startActivity(intent); // 打开系统设置GPS服务页面
							 } else if(system.platform == 'ios') {
								var UIApplication = plus.ios.import("UIApplication");
								var application2 = UIApplication.sharedApplication();
								var NSURL2 = plus.ios.import("NSURL");
								var setting2 = NSURL2.URLWithString("App-Prefs:root=Privacy&path=LOCATION");
								application2.openURL(setting2);
								plus.ios.deleteObject(setting2);
								plus.ios.deleteObject(NSURL2);
								plus.ios.deleteObject(application2);
							 }
						 }
					  }
					});
				} else if(err.errMsg.indexOf('定位服务没有开启') >= 0){
					// #ifdef APP-PLUS
					// 获取是否开启定位
					let system = uni.getSystemInfoSync(); // 获取系统信息
					if (system.platform === 'android') { // 判断平台
					    var context = plus.android.importClass("android.content.Context");
					    var locationManager = plus.android.importClass("android.location.LocationManager");
					    var main = plus.android.runtimeMainActivity();
					    var mainSvr = main.getSystemService(context.LOCATION_SERVICE);
					    if (!mainSvr.isProviderEnabled(locationManager.GPS_PROVIDER)) {
					        var main = plus.android.runtimeMainActivity();
							var Intent = plus.android.importClass('android.content.Intent');
							var Settings = plus.android.importClass('android.provider.Settings');
							var intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
							main.startActivity(intent); // 打开系统设置GPS服务页面
					    }
					} else if (system.platform === 'ios') {
					    var cllocationManger = plus.ios.import("CLLocationManager");
					    var enable = cllocationManger.locationServicesEnabled();
					    var status = cllocationManger.authorizationStatus();
					    plus.ios.deleteObject(cllocationManger);
					    console.log("手机系统的定位没有打开");
					    uni.showModal({
					        title: '提示',
					        content: '请打开定位服务功能',
					        showCancel: false, // 不显示取消按钮
					        success() {
					            var UIApplication = plus.ios.import("UIApplication");
					            var application2 = UIApplication.sharedApplication();
					            var NSURL2 = plus.ios.import("NSURL");
					            var setting2 = NSURL2.URLWithString("App-Prefs:root=Privacy&path=LOCATION");
					            application2.openURL(setting2);
					            plus.ios.deleteObject(setting2);
					            plus.ios.deleteObject(NSURL2);
					            plus.ios.deleteObject(application2);
					        }
					    });
					}
					// #endif
				}
			},
		})
	}
	
	if(!props.lazy) {
		getLocation()
	}
	
	// 点击定位城市
	function locationCity(curCity){
		if(curCity){
			emits("selectCity", curCity);
		} else {
			// 获取定位
			return getLocation()
		}
	}
	
	let inputValue = ref('')
	let searchData = ref([])
	let hasNoData = ref(false)
	//搜索
	function searchChange(value) {
		inputValue.value = value;
		
		if (inputValue.value) {
			let reg = new RegExp('^' + inputValue.value.toLowerCase());
			const result = [];
			cityList.value.map(v => {
				v.list.forEach((item) => {
					if (reg.test(item[props.spellName].toLowerCase()) || reg.test(item[props.labelName])) result.push(item);
				});
			})
			searchData.value = result;
			if (searchData.value.length === 0) {
				hasNoData.value = true;
			} else {
				hasNoData.value = false;
			}
		} else {
			searchData.value = [];
		}
	}
	
	// 跳转的索引的字母
	let toIndex = ref("")
	function selectCity(item) {
		// 设置历史访问
		setRecordList(item)
		emits("selectCity", item[props.labelName]);
		// 当前项目是需要选择到区域，所以选择城市后回到区县的地方
		toIndex.value = 'area';
		setTimeout(() => {
			toIndex.value = '';
		}, 1000);
	}
	
	const instance = getCurrentInstance(); // 获取组件实例
	let letterDetails = []
	let currentLetter = ref('area') //默认选择
	//列表滚动，和右边字母表对应
	function scrollHandle(e) {
		let view = uni.createSelectorQuery().in(instance).selectAll('.list-item');
		view.boundingClientRect((d) => {
			let top = d[0].top;
			d.forEach((item) => {
				item.top = item.top - top;
				item.bottom = item.bottom - top;
				letterDetails.push({
					id: item.id,
					top: item.top,
					bottom: item.bottom,
				});
			});
		})
		.exec();
	
		const scrollTop = e.detail.scrollTop;
		letterDetails.some((item) => {
			if (scrollTop >= item.top && scrollTop <= item.bottom - 20) {
				currentLetter.value = item.id;
				//当前固定用的是粘性定位，如果不用粘性定位，在这里设置
				return true;
			}
		});
	}
	
	// 触发开始
	function touchStart(e) {
		// console.log(e);
	}
	
	let tipsLetter = ref('') // 滑动显示字母
	//移动时
	function touchMove(e) {
		// 取消事件的默认动作，通知 Web 浏览器不要执行与事件关联的默认动作，不加浏览器下拉会触发整个页面下拉
		e.preventDefault();
		
		let y = e.touches[0].clientY;
		let offsettop = e.currentTarget.offsetTop;
	
		//判断选择区域,只在选择区才会生效
		if (y > offsettop) {
			let num = parseInt((y - offsettop) / 15); //右边每个字母元素的高度
			let letter = alphabet.value[num];
			if(tipsLetter.value == letter) return;
			
			uni.vibrateShort();
			tipsLetter.value = letter;
			toIndex.value = tipsLetter.value;
			let curentLetter = letterTransform(letter);
			uni.showToast({
				title: curentLetter,
				icon: 'none',
			});
		}
	}
	
	//触发结束
	function touchEnd() {
		toIndex.value = tipsLetter.value;
		currentLetter.value = tipsLetter.value;
	}
	
	//移动结束设置字母，赋值到toIndex
	function setLetter() {
		toIndex.value = tipsLetter.value;
		currentLetter.value = tipsLetter.value;
	}
	
	//移动开始获取字母，并放大提示
	function getLetter(e) {
		let {
			id
		} = e.currentTarget;
		if(tipsLetter.value == id) return;
		
		uni.vibrateShort();
		tipsLetter.value = id;
		let curentLetter = letterTransform(id);
		uni.showToast({
			title: curentLetter,
			icon: 'none',
		});
	}
	
	//提示字母转换
	function letterTransform(letter) {
		let str = '';
		if (letter == 'area') {
			str = '当前';
		} else if (letter == 'record') {
			str = '历史';
		} else {
			str = letter;
		}
		return str;
	}
</script>

<style lang="scss" scoped>
	.chose-city {
		padding-top: 30rpx;
		background: #fff;
	}
	.reach-content {
		padding-left: 36rpx;
		box-sizing: border-box;
		.li {
			width: 714rpx;
			font-size: 28rpx;
			height: 100rpx;
			line-height: 100rpx;
			color: #333;
			position: relative;
			box-sizing: border-box;
			border-bottom: 2rpx solid #F5F5F5;
		}
	}

	.block {
		padding: 0 36rpx;
		box-sizing: border-box;
	}

	.top-search {
		line-height: 72rpx;
		padding: 14rpx 30rpx 0;
		box-sizing: border-box;
		margin-bottom: 26rpx;

		.item {
			background: #F5F5F5;
			border-radius: 12rpx;
			font-size: 28rpx;
			text-align: center;
			color: #999999;
			/* #ifdef MP-ALIPAY */
			height: 72rpx;
			line-height: 72rpx;

			/* #endif */
			text {
				padding-left: 20rpx;
				color: #c1c2cd;
				vertical-align: middle;
				position: relative;
				top: -4rpx;
			}

		}
	}

	.scroll-view {
		width: 100%;
		height: calc(100vh - 110rpx);
		box-sizing: border-box;
	}

	.area {
		margin-bottom: 8rpx;

		.title-wrapp {
			position: sticky;
			top: 0;
			left: 0;
			background: #fff;
			z-index: 99;
		}

		.c-title {
			width: 100%;
			box-sizing: border-box;
			font-size: 28rpx;
			color: #999999;
			margin-bottom: 24rpx;
			display: inline-flex;
			justify-content: space-between;
			align-items: center;

			.r {
				font-size: 24rpx;
				color: #8e8f97;
				display: inline-block;
				align-items: center;

				.iconfont {
					font-size: 24rpx;
				}
			}
		}

		.ul {
			display: flex;
			flex-wrap: wrap;

			.li {
				width: 155rpx;
				padding: 0 10rpx;
				box-sizing: border-box;
				height: 68rpx;
				line-height: 68rpx;
				text-align: center;
				font-size: 32rpx;
				color: #333;
				border-radius: 8rpx;
				margin: 0 18rpx 28rpx 0;
				border: 2rpx solid #E2E2E2;

				&:nth-child(4n) {
					margin-right: 0;
				}

				&.now {
					width: auto;
					padding: 0 28rpx 0 18rpx;
					display: flex;
					justify-content: center;
					align-items: center;
				}

				&.active {
					font-weight: 500;
					background: #ffde45;
				}
			}

			.hover {
				background: #ffde45;
			}
		}
	}

	.city-list {
		width: 750rpx;
		padding-bottom: 50rpx;

		.c-title {
			height: 60rpx;
			line-height: 60rpx;
			font-size: 30rpx;
			font-weight: 500;
			color: #272636;
			background: #fff;
			box-sizing: border-box;
			padding-left: 36rpx;
			position: sticky;
			top: 0;
			left: 0;
			z-index: 2;
		}

		.item {
			width: 714rpx;
			margin-left: 36rpx;
			padding: 0 36rpx 0 0;
			height: 100rpx;
			line-height: 100rpx;
			color: #333;
			font-size: 28rpx;
			box-sizing: border-box;
			border-bottom: 2rpx solid #F5F5F5;
		}
	}

	.alphabet {
		position: fixed;
		right: 0;
		bottom: 20%;
		width: calc(750rpx - 680rpx);
		text-align: center;
		font-size: 20rpx;
		font-weight: 700;
		color: #8e8f97;
		z-index: 99;

		.item {
			height: 15px;
			line-height: 15px;
		}
	}

	.has-no-data {
		font-size: 24rpx;
		text-align: center;
		color: #8e8f97;
		margin-top: 50rpx;
	}
</style>
